package com.byb.server.service.impl;

import com.byb.server.domain.WcInsuranceCategory;
import com.byb.server.repository.WcClaimCasesRepository;
import com.byb.server.repository.WcInsuranceCategoryRepository;
import com.byb.server.service.WcProductService;
import com.byb.server.domain.WcProduct;
import com.byb.server.repository.WcProductRepository;
import com.byb.server.repository.search.WcProductSearchRepository;
import com.byb.server.service.WcQuestionService;
import com.byb.server.service.dto.Wc.ClaimCaseDTO;
import com.byb.server.service.dto.Wc.ProductRankDTO;
import com.byb.server.service.dto.Wc.WcProductDetialForFontEndDTO;
import com.byb.server.service.dto.Wc.WcProductForFontEndDTO;
import com.byb.server.service.dto.WcClaimCasesDTO;
import com.byb.server.service.dto.WcProductDTO;
import com.byb.server.service.mapper.Wc.ProductRankMapper;
import com.byb.server.service.mapper.Wc.WcProductDetialForFontEndMapper;
import com.byb.server.service.mapper.Wc.WcSearchProductMapper;
import com.byb.server.service.mapper.WcClaimCasesMapper;
import com.byb.server.service.mapper.WcProductMapper;
import com.byb.server.service.util.WcUtil.WcProductbyInsurer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static org.elasticsearch.index.query.QueryBuilders.*;

/**
 * Service Implementation for managing WcProduct.
 */
@Service
@Transactional
public class WcProductServiceImpl implements WcProductService {

    private final Logger log = LoggerFactory.getLogger(WcProductServiceImpl.class);

    private final WcProductRepository wcProductRepository;

    private final WcProductMapper wcProductMapper;

    private final WcProductSearchRepository wcProductSearchRepository;

    private final WcSearchProductMapper wcSearchProductMapper;

    private final WcProductDetialForFontEndMapper wcProductDetialForFontEndMapper;

    private final ProductRankMapper productRankMapper;

    private final WcQuestionService wcQuestionService;

    private final WcClaimCasesRepository wcClaimCasesRepository;

    private final WcClaimCasesMapper wcClaimCasesMapper;

    private final WcInsuranceCategoryRepository wcInsuranceCategoryRepository;

    public WcProductServiceImpl(WcProductRepository wcProductRepository, WcProductMapper wcProductMapper, WcProductSearchRepository wcProductSearchRepository, WcSearchProductMapper wcSearchProductMapper, WcProductDetialForFontEndMapper wcProductDetialForFontEndMapper, ProductRankMapper productRankMapper, WcQuestionService wcQuestionService, WcClaimCasesRepository wcClaimCasesRepository, WcClaimCasesMapper wcClaimCasesMapper, WcInsuranceCategoryRepository wcInsuranceCategoryRepository) {
        this.wcProductRepository = wcProductRepository;
        this.wcProductMapper = wcProductMapper;
        this.wcProductSearchRepository = wcProductSearchRepository;
        this.wcSearchProductMapper = wcSearchProductMapper;
        this.wcProductDetialForFontEndMapper = wcProductDetialForFontEndMapper;
        this.productRankMapper = productRankMapper;
        this.wcQuestionService = wcQuestionService;
        this.wcClaimCasesRepository = wcClaimCasesRepository;
        this.wcClaimCasesMapper = wcClaimCasesMapper;
        this.wcInsuranceCategoryRepository = wcInsuranceCategoryRepository;
    }

    /**
     * Save a wcProduct.
     *
     * @param wcProductDTO the entity to save
     * @return the persisted entity
     */
    @Override
    public WcProductDTO save(WcProductDTO wcProductDTO) {
        log.debug("Request to save WcProduct : {}", wcProductDTO);
        WcProduct wcProduct = wcProductMapper.toEntity(wcProductDTO);
        wcProduct = wcProductRepository.save(wcProduct);
        WcProductDTO result = wcProductMapper.toDto(wcProduct);
        return result;
    }

    /**
     * Get all the wcProducts.
     *
     * @param pageable the pagination information
     * @return the list of entities
     */
    @Override
    @Transactional(readOnly = true)
    public Page<WcProductDTO> findAll(Pageable pageable) {
        log.debug("Request to get all WcProducts");
        return wcProductRepository.findAll(pageable)
            .map(wcProductMapper::toDto);
    }

    /**
     * Get one wcProduct by id.
     *
     * @param id the id of the entity
     * @return the entity
     */
    @Override
    @Transactional(readOnly = true)
    public WcProductDTO findOne(Long id) {
        log.debug("Request to get WcProduct : {}", id);
        WcProduct wcProduct = wcProductRepository.findOne(id);
        return wcProductMapper.toDto(wcProduct);
    }

    /**
     * Delete the  wcProduct by id.
     *
     * @param id the id of the entity
     */
    @Override
    public void delete(Long id) {
        log.debug("Request to delete WcProduct : {}", id);
        wcProductRepository.delete(id);
        // wcProductSearchRepository.delete(id);
    }

    /**
     * Search for the wcProduct corresponding to the query.
     *
     * @param query    the query of the search
     * @param pageable the pagination information
     * @return the list of entities
     */
    @Override
    @Transactional(readOnly = true)
    public Page<WcProductDTO> search(String query, Pageable pageable) {
        log.debug("Request to search for a page of WcProducts for query {}", query);
        Page<WcProduct> result = wcProductSearchRepository.search(queryStringQuery(query), pageable);
        return result.map(wcProductMapper::toDto);
    }

    /**
     * 微信-公司，险种 参数 筛选产品数据聚合
     *
     * @param insurerId
     * @param categoryId
     * @param pageable
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public List<WcProductForFontEndDTO> getProdcutForWc(Long insurerId, Long categoryId, Pageable pageable) {
        List<WcProductForFontEndDTO> result = null;
        Optional insurerIdOptional = Optional.ofNullable(insurerId);
        Optional categoryIdOptional = Optional.ofNullable(categoryId);
        if (insurerIdOptional.isPresent() && categoryIdOptional.isPresent()) {
            result = WcProductbyInsurer.productbyType(wcProductRepository.findAllByWcIsurerAndWcInsuranceCategory(insurerId, categoryId, pageable).map(wcSearchProductMapper::toDto).getContent(), false);
        } else if (insurerIdOptional.isPresent()) {
            result = WcProductbyInsurer.productbyType(wcProductRepository.findAllByWcIsurer(insurerId, pageable).map(wcSearchProductMapper::toDto).getContent(), false);
        } else if (categoryIdOptional.isPresent()) {
            result = WcProductbyInsurer.productbyType(wcProductRepository.findAllByWcInsuranceCategory(categoryId, pageable).map(wcSearchProductMapper::toDto).getContent(), false);
        } else {
            result = WcProductbyInsurer.productByInsurer(wcProductRepository.findAll(pageable).map(wcSearchProductMapper::toDto).getContent(), wcProductRepository.findGroupByWcInsurer(pageable), true);
        }
        return result;
    }

    @Override
    @Transactional(readOnly = true)
    public WcProductDetialForFontEndDTO getProductDetail(Long id, Pageable pageable) {
        WcProduct wcProduct = wcProductRepository.findOne(id);
        WcProductDetialForFontEndDTO wcProductDetialForFontEndDTO = wcProductDetialForFontEndMapper.toDto(wcProduct);
        List<ProductRankDTO> productRankDTOS = wcProductRepository.findAllLime20(wcProduct.getWcInsuranceCategory().getId()).stream().sorted(Comparator.comparing(WcProduct::getDoubleScore).reversed()).map(productRankMapper::toDto).collect(Collectors.toList());
        wcProductDetialForFontEndDTO.setProductRankDTOList(productRankDTOS);
        wcProductDetialForFontEndDTO.setWcQuestionList(wcQuestionService.getWcQuestionByProductId(id, pageable).getContent());
        List<WcClaimCasesDTO> wcClaimCasesDTOS = wcClaimCasesRepository.findAllByWcProductId(id).stream().map(wcClaimCasesMapper::toDto).collect(Collectors.toList());
        List<Long> wcClainPartyIds = wcClaimCasesRepository.findAllByWcProductIdForwcClainPartyId(id);
        List<ClaimCaseDTO> claimCaseDTOList = new ArrayList<>();
        for (int i = 0; i < wcClainPartyIds.size(); i++) {
            List<WcClaimCasesDTO> data = new ArrayList<>();
            for (int j = 0; j < wcClaimCasesDTOS.size(); j++) {
                if (wcClainPartyIds.get(i) == wcClaimCasesDTOS.get(j).getWcClainParty().getId()) {
                    data.add(wcClaimCasesDTOS.get(j));
                }
            }
            ClaimCaseDTO claimCaseDTO = new ClaimCaseDTO();
            claimCaseDTO.setWcClainParty(data.get(0).getWcClainParty());
            claimCaseDTO.setWcClaimCasesDTOList(data);
            claimCaseDTOList.add(claimCaseDTO);
        }
        wcProductDetialForFontEndDTO.setClaimCaseDTOList(claimCaseDTOList);
        return wcProductDetialForFontEndDTO;
    }

    @Override
    public void generate() {
        List<WcProduct> list = wcProductRepository.findAll();
        List<WcInsuranceCategory> wcInsuranceCategoryList = wcInsuranceCategoryRepository.findAll();
        for (int i = 0; i < wcInsuranceCategoryList.size(); i++) {
            List<WcProduct> result = new ArrayList<>();
            for (int j = 0; j < list.size(); j++) {
                if (list.get(j).getWcInsuranceCategory().getId() == wcInsuranceCategoryList.get(i).getId()) {
                    result.add(list.get(j));
                }
            }
            if (result.size() != 0) {
                for (int k = 0; k < result.size(); k++) {
                    result.get(k).setRanking(String.valueOf(k + 1));
                }
                result.stream().map(wcProductRepository::save);
            }
        }
    }

    @Override
    public void saveBatchProduct(List<WcProductDTO> list) {
        wcProductRepository.save(list.stream().map(wcProductMapper::toEntity).collect(Collectors.toList()));
    }
}
